package com.tanhua.dubbo.api.impl.mongo;

import com.mongodb.client.result.UpdateResult;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.*;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVo;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.PublishApi;
import com.tanhua.dubbo.utils.IdService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service(timeout = 5000)
public class PublishApiImpl implements PublishApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IdService idService;

    @Reference
    private UserInfoApi userInfoApi;

    /**
     * 保存动态
     *
     * @param publish
     */
    @Override
    public void save(Publish publish) {
        //给publish设置pid
        publish.setPid(idService.getNextId("quanzi_publish"));
        //1. 动态表要插入一条数据
        mongoTemplate.insert(publish);
        //2. 自己的相册表插入数据
        Album album = new Album();
        album.setPublishId(publish.getId());
        album.setCreated(System.currentTimeMillis());
        mongoTemplate.insert(album, "quanzi_album_" + publish.getUserId());
        //3. 查询我有哪些的好友
        Query query = new Query(Criteria.where("userId").is(publish.getUserId()));
        List<Friend> friendList = mongoTemplate.find(query, Friend.class);
        //4. 往好友的时间线表插入记录
        if (friendList != null) {
            for (Friend friend : friendList) {
                TimeLine timeLine = new TimeLine();
                timeLine.setUserId(publish.getUserId());
                timeLine.setPublishId(publish.getId());
                timeLine.setCreated(System.currentTimeMillis());
                mongoTemplate.insert(timeLine, "quanzi_time_line_" + friend.getFriendId());
            }
        }

    }


    /**
     * 查看好友的动态
     *
     * @param page
     * @param pagesize
     * @param userId
     * @return
     */
    @Override
    public PageResult findByTimeLine(Integer page, Integer pagesize, Long userId) {
        //排序
        Query query = new Query();
        query.with(Sort.by(Sort.Order.desc("created")));
        query.limit(pagesize).skip((page - 1) * pagesize);
        List<TimeLine> timeLineList = mongoTemplate.find(query, TimeLine.class, "quanzi_time_line_" + userId);
        Long count = mongoTemplate.count(query, TimeLine.class, "quanzi_time_line_" + userId);

        //通过遍历时间线表查找publish
        List<Publish> publishList = new ArrayList<>();
        if (timeLineList != null) {
            for (TimeLine timeLine : timeLineList) {
                Publish publish = mongoTemplate.findById(timeLine.getPublishId(), Publish.class);
                //注意： 由于测试数据的不完整性，实现时间线表的某些动态的id是没有对应的publish某一个记录的
                if (publish != null&&publish.getState()==1) {
                    publishList.add(publish);
                }
            }
        }

        PageResult pageResult = new PageResult(page, pagesize, count.intValue(), publishList);
        return pageResult;
    }

    /**
     * 查询推荐表，查询到推荐的朋友圈
     *
     * @param page
     * @param pagesize
     * @param userId
     * @return
     */
    @Override
    public PageResult queryRecommendPublishList(Integer page, Integer pagesize, Long userId) {
        //1. 查询推荐圈子表得到推荐的圈子信息
        Query query = new Query(Criteria.where("userId").is(userId).and("state").is(1));
        query.with(Sort.by(Sort.Order.desc("created")));
        query.limit(pagesize).skip((page - 1) * pagesize);
        List<RecommendQuanzi> recommendQuanziList = mongoTemplate.find(query, RecommendQuanzi.class);
        Long count = mongoTemplate.count(query, RecommendQuanzi.class);

        //遍历推荐动态表，得到动态动态
        List<Publish> publishList = new ArrayList<>();
        if (recommendQuanziList != null) {
            for (RecommendQuanzi recommendQuanzi : recommendQuanziList) {
                Publish publish = mongoTemplate.findById(recommendQuanzi.getPublishId(), Publish.class);
                //注意： 由于测试数据的不完整性，实现时间线表的某些动态的id是没有对应的publish某一个记录的
                if (publish != null) {
                    publishList.add(publish);
                }
            }
        }

        PageResult pageResult = new PageResult(page, pagesize, count.intValue(), publishList);
        return pageResult;
    }

    //根据id查找动态
    @Override
    public Publish findById(String publishId) {
        Publish publish = mongoTemplate.findById(new ObjectId(publishId), Publish.class);
        return publish;
    }

    @Override
    public PageResult queryMyPublishList(Integer page, Integer pagesize, Long userId) {
        // 创建查询对象
        Query query = new Query();
        // 指定排序参数
        query.with(Sort.by(Sort.Direction.DESC, "created"));
        // 指定分页参数
        query.limit(pagesize).skip((page - 1) * pagesize);
        // 查询当前用户的相册表
        List<Album> albumList = mongoTemplate.find(query, Album.class, "quanzi_album_" + userId);
        // 获取总条数
        long count = mongoTemplate.count(query, Album.class, "quanzi_album_" + userId);
        List<Publish> publishList = new ArrayList<>();
        if (albumList != null) {
            for (Album album : albumList) {
                // 根据动态id查询发布动态表
                Publish publish = mongoTemplate.findById(album.getPublishId(), Publish.class);
                if (publish != null&&publish.getState()==1) {
                    publishList.add(publish);
                }
            }
        }

        return new PageResult(page, pagesize, (int) count, publishList);
    }

    @Override
    public PageResult findPublishList(Integer page, Integer pagesize, Long uid, String state) {
        PageResult pageResult = null;
        if (Objects.nonNull(uid)) {
            return queryMyPublishList(page, pagesize, uid);
        } else if (StringUtils.isBlank(state)) {
            pageResult = getPageResult(page, pagesize, null);
        } else if ("0".equals(state)) { //待审核
            pageResult = getPageResult(page, pagesize, state);
        } else if ("1".equals(state)) { //已审核
            pageResult = getPageResult(page, pagesize, state);
        } else if ("2".equals(state)) { // 已驳回
            pageResult = getPageResult(page, pagesize, state);
        }else if ("''".equals(state)){
            pageResult = getPageResult(page, pagesize, null);
        }
        return pageResult;
    }


    private PageResult getPageResult(Integer page, Integer pagesize, String state) {

        PageResult pageResult; //定义PageResult对象的变量

        Query query = null; //定义Query对象的变量
        if (Objects.isNull(state)) {
            //如果state的值为空，就是查询集合中的所有数据
            query = new Query(Criteria.where("state").exists(true));
        } else {
            //否者就是根据state进行查询
            query = new Query(Criteria.where("state").is(Integer.parseInt(state)));
            //根据时间倒序排序
            query.with(Sort.by(Sort.Order.desc("created")));
        }
        //查询数据库中的数据
        List<Publish> publishList = mongoTemplate.find(query, Publish.class);


        //查询数据瞒住query条件的数据的数量
        long count = mongoTemplate.count(query, Publish.class);
        //创建PublishVo类的集合，封装数据
        ArrayList<PublishVo> publishVos = new ArrayList<>();
        for (Publish publish : publishList) {
            //根据圈子中的用户id查询用户的基本信息
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
            //创建一个vo封装数据
            PublishVo publishVo = new PublishVo();
            if (userInfo != null) {
                BeanUtils.copyProperties(userInfo, publishVo);
            }
            List<String> medias = publish.getMedias(); //设置图片列表
            if (medias != null) {
                publishVo.setImageContent(medias);
            }
            publishVo.setUserId(publish.getUserId().intValue());//设置用户id
            publishVo.setState(publish.getState().toString());//设置state的值
            publishVo.setLickCount(publish.getLikeCount());//设置点赞数
            publishVo.setId(publish.getId().toString()); //设置动态id
            publishVo.setCreateDate(publish.getCreated());//设置创建花时间
            BeanUtils.copyProperties(publish, publishVo);
            //添加到集合中
            publishVos.add(publishVo);
        }
        //返回PageResult对象
        pageResult = new PageResult(page, pagesize, (int) count, publishVos);
        return pageResult;
    }


    @Override
    public void updateState(Publish publish, int state) {
        Query query = new Query(Criteria.where("_id").is(publish.getId()));
        Update update = new Update();
        update.set("state", state);
        mongoTemplate.updateFirst(query, update, Publish.class);
    }

    /**
     * 根据pid的集合查找动态
     *
     * @param pList
     * @return
     */
    @Override
    public List<Publish> findByPids(List<Long> pList) {
        Query query = new Query(Criteria.where("pid").in(pList));
        List<Publish> publishList = mongoTemplate.find(query, Publish.class);
        return publishList;
    }


    @Override
    public Long reject(List<String> publishId) {
        return getaLong(publishId, 2);
    }


    @Override
    public Long pass(List<String> publishId) {
        return getaLong(publishId, 1);
    }

    private Long getaLong(List<String> publishId, int i) {
        UpdateResult updateResult = null;
        if (Objects.nonNull(publishId)) {
            ArrayList<ObjectId> objectIds = new ArrayList<>();
            //通过lambda遍历publishId集合，创建ObjectId对象
            publishId.forEach(pid -> objectIds.add(new ObjectId(pid)));
            //条件，看数据库中集合_id是否包含objectIds集合的publishId
            Query query = new Query(Criteria.where("_id").in(objectIds));
            //更新数据
            Update update = new Update();
            update.set("state", i);
            updateResult = mongoTemplate.updateMulti(query, update, Publish.class);

        }
        //返回结果
        return updateResult.getMatchedCount();
    }

}
